package com.acctrue.zentao.utils;

import com.acctrue.zentao.dto.LoginDTO;
import com.acctrue.zentao.dto.TaskDTO;
import com.acctrue.zentao.dto.ProjectDTO;
import com.acctrue.zentao.enums.ModuleTypeEnum;
import com.acctrue.zentao.enums.TaskTypeEnum;
import com.google.common.collect.Lists;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 请求禅道接口工具类
 *
 * @author: 孙炯炯
 * @since: 2023/8/18
 **/
public class ZentaoUtils {
    public static final String sessionUrl = "/api-getsessionid.json";
    public static final String loginUrl = "/user-login-%s.json";
    public static final String projectListUrl = "/project-all-undone-.json";
    public static final String taskListUrl = "/my-task-assignedTo-id_desc-1000-1000-1.json";
    public static final String bugListUrl = "/my-bug-assignedTo-id_desc-1000-1000-1.json";

    /**
     * 禅道登录
     *
     * @param input
     * @return
     */
    public static ResponseResult<LoginDTO.Output> login(LoginDTO.Input input) {
        // 请求session
        ResponseResult<String> sessionResult = OkHttpUtil.doGet(input.getUrl(ZentaoUtils.sessionUrl));
        ResponseResult<LoginDTO.Output> outResult = copyResponseResult(sessionResult);
        if (!sessionResult.getSuccess()) {
            return outResult;
        }
        JsonObject sessionResultJson = JsonParser.parseString(sessionResult.getData()).getAsJsonObject();
        String status = sessionResultJson.get("status").getAsString();
        if (!"success".equalsIgnoreCase(status)) {
            outResult.setMessage(sessionResultJson.get("reason").getAsString());
            outResult.setSuccess(false);
            return outResult;
        }
        JsonObject sessionDataJson = JsonParser.parseString(sessionResultJson.get("data").getAsString()).getAsJsonObject();
        String sessionName = sessionDataJson.get("sessionName").getAsString();
        String sessionID = sessionDataJson.get("sessionID").getAsString();
        LoginDTO.Output output = new LoginDTO.Output();
        output.setSessionID(sessionID);
        output.setSessionName(sessionName);
        // 登录
        Map param = new HashMap<String, Object>(2);
        param.put("account", input.getUserName());
        param.put("password", input.getPassword());
        ResponseResult<String> loginResult = OkHttpUtil.doFormData(input.getUrl(String.format(loginUrl, sessionID)), param, null);
        outResult = copyResponseResult(loginResult);
        if (!outResult.getSuccess()) {
            return outResult;
        }
        JsonObject loginResultJson = JsonParser.parseString(loginResult.getData()).getAsJsonObject();
        status = loginResultJson.get("status").getAsString();
        if (!"success".equalsIgnoreCase(status)) {
            outResult.setMessage(loginResultJson.get("reason").getAsString());
            outResult.setSuccess(false);
            return outResult;
        }
        JsonObject loginUserJson = loginResultJson.getAsJsonObject("user");
        String token = loginUserJson.get("token").getAsString();
        output.setToken(token);
        outResult.setData(output);
        return outResult;
    }

    /**
     * 请求禅道项目列表
     * @param input
     * @return
     */
    public static ResponseResult<List<ProjectDTO.Output>> searchProjectList(ProjectDTO.Input input) {
        // 请求项目列表
        Map head = new HashMap(1);
        head.put(input.getSessionName(), input.getToken());
        head.put("Cookie", OkHttpUtil.buildCookie(head));
        ResponseResult<String> projectResult = OkHttpUtil.doGet(input.getUrl(ZentaoUtils.projectListUrl), null, head);
        ResponseResult<List<ProjectDTO.Output>> outResult = copyResponseResult(projectResult);
        if (!projectResult.getSuccess()) {
            return outResult;
        }
        JsonObject resultJson = JsonParser.parseString(projectResult.getData()).getAsJsonObject();
        String status = resultJson.get("status").getAsString();
        if (!"success".equalsIgnoreCase(status)) {
            outResult.setMessage(resultJson.get("reason").getAsString());
            outResult.setSuccess(false);
            return outResult;
        }
        JsonObject dataJson = JsonParser.parseString(resultJson.get("data").getAsString()).getAsJsonObject();
        JsonObject projectsJson = dataJson.get("projects").getAsJsonObject();
        List<ProjectDTO.Output> outputList = new ArrayList<>();
        for (String id : projectsJson.keySet()) {
            ProjectDTO.Output output = new ProjectDTO.Output();
            output.setId(id);
            output.setName(projectsJson.get(id).getAsString());
            outputList.add(output);
        }
        outResult.setData(outputList);
        return outResult;
    }

    /**
     * 请求禅道获取任务列表
     *
     * @param input
     * @return
     */
    public static ResponseResult<List<TaskDTO.Output>> searchTaskList(TaskDTO.Input input) {
        List<TaskDTO.Output> list = Lists.newArrayListWithExpectedSize(20);
        Map head = new HashMap(1);
        head.put(input.getSessionName(), input.getToken());
        head.put("Cookie", OkHttpUtil.buildCookie(head));
        // 查询bug
        if (Boolean.TRUE.equals(input.getAreBug())) {
            ResponseResult<String> bugResult = OkHttpUtil.doGet(input.getUrl(ZentaoUtils.bugListUrl), null, head);
            ResponseResult<List<TaskDTO.Output>> outResult = copyResponseResult(bugResult);
            if (!bugResult.getSuccess()) {
                return outResult;
            }
            List<TaskDTO.Output> outputs = buildBugList(bugResult.getData());
            list.addAll(outputs);
        }
        // 查询任务
        if (input.getTaskTypes() != null && input.getTaskTypes().size() > 0) {
            ResponseResult<String> taskResult = OkHttpUtil.doGet(input.getUrl(ZentaoUtils.taskListUrl), null, head);
            ResponseResult<List<TaskDTO.Output>> outResult = copyResponseResult(taskResult);
            if (!taskResult.getSuccess()) {
                return outResult;
            }
            List<TaskDTO.Output> outputs = buildTaskList(taskResult.getData());
            outputs = outputs.stream().filter(p -> input.getTaskTypes().contains(p.getType()) && input.getTaskStatus().contains(p.getStatus())).collect(Collectors.toList());
            list.addAll(outputs);
        }
        // 项目筛选
        if (StringUtils.isNotEmpty(input.getProjectId())) {
            list = list.stream().filter(p -> input.getProjectId().equals(p.getProjectId())).collect(Collectors.toList());
        }
        return ResponseResult.success(list);
    }

    public static <T> ResponseResult<T> copyResponseResult(ResponseResult input) {
        ResponseResult<T> out = new ResponseResult<>();
        out.setCode(input.getCode());
        out.setDetails(input.getDetails());
        out.setMessage(input.getMessage());
        out.setSuccess(input.getSuccess());

        return out;
    }

    private static List<TaskDTO.Output> buildBugList(String data) {
        List<TaskDTO.Output> list = Lists.newArrayListWithExpectedSize(20);
        JsonObject bugResultJson = JsonParser.parseString(data).getAsJsonObject();
        JsonObject bugDataJson = JsonParser.parseString(bugResultJson.get("data").getAsString()).getAsJsonObject();
        JsonArray bugsJsonArray = bugDataJson.get("bugs").getAsJsonArray();
        for (int i = 0; i < bugsJsonArray.size(); i++) {
            JsonObject bugJson = bugsJsonArray.get(i).getAsJsonObject();
            TaskDTO.Output output = new TaskDTO.Output();
            output.setId(StringUtils.getString(bugJson.get("id")));
            output.setProjectId(StringUtils.getString(bugJson.get("project")));
            output.setTitle(StringUtils.getString(bugJson.get("title")));
            output.setType(TaskTypeEnum.BUG.getValue());
            output.setStatus(StringUtils.getString(bugJson.get("status")));
            output.setOpenedBy(StringUtils.getString(bugJson.get("openedBy")));
            output.setOpenedDate(StringUtils.getString(bugJson.get("openedDate")));
            output.setDeadline(StringUtils.getString(bugJson.get("deadline")));
            output.setModuleType(ModuleTypeEnum.BUG);
            list.add(output);
        }
        return list;
    }

    private static List<TaskDTO.Output> buildTaskList(String data) {
        List<TaskDTO.Output> list = Lists.newArrayListWithExpectedSize(20);
        JsonObject taskResultJson = JsonParser.parseString(data).getAsJsonObject();
        JsonObject taskDataJson = JsonParser.parseString(taskResultJson.get("data").getAsString()).getAsJsonObject();
        JsonArray taskJsonArray = taskDataJson.get("tasks").getAsJsonArray();
        for (int i = 0; i < taskJsonArray.size(); i++) {
            JsonObject bugJson = taskJsonArray.get(i).getAsJsonObject();
            TaskDTO.Output output = new TaskDTO.Output();
            output.setId(StringUtils.getString(bugJson.get("id")));
            output.setProjectId(StringUtils.getString(bugJson.get("project")));
            output.setTitle(StringUtils.getString(bugJson.get("name")));
            output.setType(StringUtils.getString(bugJson.get("type")));
            output.setStatus(StringUtils.getString(bugJson.get("status")));
            output.setOpenedBy(StringUtils.getString(bugJson.get("openedBy")));
            output.setOpenedDate(StringUtils.getString(bugJson.get("openedDate")));
            output.setDeadline(StringUtils.getString(bugJson.get("deadline")));
            output.setModuleType(ModuleTypeEnum.TASK);
            list.add(output);
        }
        return list;
    }
}
